dojo.provide("lotex.Form");

dojo.require("dojo.lang.declare");
dojo.require("dojo.lang.func");
dojo.require("lotex.html.Html");

lotex.Forms = {
    cache: {},
    add: function(name, form) {
        this.cache[name] = form;
    },
    get: function(name) {
        return this.cache[name];
    }
};


dojo.declare("lotex.Form", null,
    function(/*new lotex.Form(name) or new lotex.Form(name, htmlid)*/) {
        if(arguments.length>=1)
            this.name = arguments[0];
        else
            this.name = 'lotexForm';

        if(arguments.length==2)
            this.htmlid = arguments[1];

        lotex.Forms.add(this.name, this);
    },
{
    onSubmitStart: null,
    onSubmitEnd: null,
    onSubmitError: null,

    onLoad: function(response) {
        if(response.done) {
            if(response.form) {
                var fm = new lotex.html.Form().setProp('name','ds')
                    .setProp('id','ds').loadFromJson(response.form);
                var ret = fm.toHtml();
                dojo.byId(this.htmlid).innerHTML += ret;
                // >>>
                this.form = fm;
            }
        } else {
            if(response.message) alert(response.message);
            else alert("Response not valid JSON!");
        }
    },

    load: function() {
        // >>>
        this.loadArgs = lotex.api.args(this.load);

        this.modelName = this.loadArgs.args[0];

        if((!this.loadArgs.load)&&(!dojo.lang.isFunction(this.loadArgs.load)))
            this.loadArgs.load = dojo.lang.hitch(this, "onLoad");

        // 从参数中剥离事件。
        if(this.loadArgs.submitStart&&
            dojo.lang.isFunction(this.loadArgs.submitStart))
            this.onSubmitStart = this.loadArgs.submitStart;

        if(this.loadArgs.submitEnd&&
            dojo.lang.isFunction(this.loadArgs.submitEnd))
            this.onSubmitEnd = this.loadArgs.submitEnd;

        if(this.loadArgs.submitError&&
            dojo.lang.isFunction(this.loadArgs.submitError))
            this.onSubmitError = this.loadArgs.submitError;

        lotex.api.form(this.loadArgs);
    },

    submit: function() {
        if(this.onSubmitStart!=null)this.onSubmitStart();
        this._submit();
    },

    _submit: function() {
        this.submitByApi();
    },

    submitByApi: function() {
        var formId = this.form.getProp('id');
        if(this.onSubmitEnd==null) {
            this.onSubmitEnd = function(response) {
                if(response.done) {
                    if(response.id) alert(response.id);
                } else {
                    if(response.message) alert(response.message);
                    else alert("Response not valid JSON!");
                }
            }
        }

        var kw = {
            args: [
                this.modelName,
                lotex.encodeForm(dojo.byId(formId))
            ]
        };
        if(this.onSubmitEnd!=null);
            kw.load = this.onSubmitEnd;
        lotex.api.save(kw);
    },

    // FIXME
    submitByPost: function() {
        var kw = {
            url: _this.action,
            encoding: "utf-8",
            formNode: dojo.byId(_this.name),
            method: "post",
            mimetype: "text/plain",
            load: function(type, data, evt) {
                _this.onSubmitEnd(data);
            },
            error: function(t, e) {
                _this.onSubmitError(t, e);
            }
        };
        dojo.io.bind(kw);
    }
});

// TODO: Move to htmlUtils
lotex.encodeForm = function(/*DOMNode*/formNode, /*String?*/encoding, /*Function?*/formFilter){
    //summary: Converts the names and values of form elements into an URL-encoded
    //string (name=value&name=value...).
    //formNode: DOMNode
    //encoding: String?
    //      The encoding to use for the values. Specify a string that starts with
    //      "utf" (for instance, "utf8"), to use encodeURIComponent() as the encoding
    //      function. Otherwise, dojo.string.encodeAscii will be used.
    //formFilter: Function?
    //  A function used to filter out form elements. The element node will be passed
    //  to the formFilter function, and a boolean result is expected (true indicating
    //  indicating that the element should have its name/value included in the output).
    //  If no formFilter is specified, then dojo.io.formFilter() will be used.
    if((!formNode)||(!formNode.tagName)||(!formNode.tagName.toLowerCase() == "form")){
        dojo.raise("Attempted to encode a non-form element.");
    }
    if(!formFilter) { formFilter = dojo.io.formFilter; }
    var enc = /utf/i.test(encoding||"") ? encodeURIComponent : dojo.string.encodeAscii;
    var values = {};

    for(var i = 0; i < formNode.elements.length; i++){
        var elm = formNode.elements[i];
        if(!elm || elm.tagName.toLowerCase() == "fieldset" || !formFilter(elm)) { continue; }
        var name = enc(elm.name);
        var type = elm.type.toLowerCase();

        if(type == "select-multiple"){
            for(var j = 0; j < elm.options.length; j++){
                if(elm.options[j].selected) {
                    values[name] = enc(elm.options[j].value);
                }
            }
        }else if(dojo.lang.inArray(["radio", "checkbox"], type)){
            if(elm.checked){
                values[name] = enc(elm.value);
            }
        }else{
            values[name] = enc(elm.value);
        }
    }

    // now collect input type="image", which doesn't show up in the elements array
    var inputs = formNode.getElementsByTagName("input");
    for(var i = 0; i < inputs.length; i++) {
        var input = inputs[i];
        if(input.type.toLowerCase() == "image" && input.form == formNode
            && formFilter(input)) {
            var name = enc(input.name);
            values[name] = enc(input.value);
            values[name+".x"] = 0;
            values[name+".y"] = 0;
        }
    }
    return values; // Object
}